//============================================================================
// Name        : cg.h
// Author      : Yugi
// Version     : 1.0
// Description : 
//============================================================================

#ifndef _CG_H
#define _CG_H

#include <stdlib.h>
#include <dr_api.h>

#include "cfg.h"

#define DEFAULT_CG_SIZE	256

/* Call graph nodes */
typedef struct _CG_NODE {
	app_pc pc;				// address
	PCFG pcfg;				// control flow graph
} CG_NODE, *PCG_NODE;

/* Call graph */
typedef struct _CG{
	struct _CG_NODE *nodes;	// bb list
	unsigned int size;		// bb list size 
	unsigned int multiple;	// bb list max size = DEFAULT_CG_SIZE * multiple
	PINT_STACK stack;		// call stack
	struct _EDGE *head;		// edge list head
	struct _EDGE *tail;		// edge list tail
} CG, *PCG;

/* 
* Generate a new call gragh.
* 
* RETURN:	new cg
* NOTES:	Return value should be freed by user
*/
PCG cg_new();

/* 
* Insert a basic block to the call gragh.
* 
* REQUIRE:	pcg not NULL
*			pc in text seg
* RETURN:	Index of the target basic block, if the basic block
*			exist, return the existing basic block index
* MODIFY:	pcg
*/
unsigned int cg_add_node(void *drcontext, PCG pcg, app_pc pc);

/* 
* Insert an edge to the call gragh.
* 
* REQUIRE:	pcg not NULL
*			src & dst distinguishes, less than pcg->size
* RETURN:	true if edge added
* MODIFY:	pcg
*/
bool cg_add_edge(PCG pcg, unsigned int src, unsigned int dst);

/* 
* Construct a call graph. 
* 
* REQUIRE:	pcg not NULL
*			module not NULL
*			bb not NULL
* MODIFY:	pcg
*/
void cg_parse(void *drcontext, instrlist_t *bb, module_data_t *module, PCG pcg);

/* 
* Print call gragh
* 
* REQUIRE:	pcg not NULL
*			outfile not NULL
*/
void cg_print(void *drcontext, file_t outfile, PCG pcg, char *path_buf, unsigned int dir_len);

#endif /* End of _CG_H */